DepositData.tsx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. "use client";
  2. import { DepositsTypes } from "@/api/depositsApi";
  3. import { getUserRechargeApi } from "@/api/user";
  4. import Box from "@/components/Box";
  5. import { useUserInfoStore } from "@/stores/useUserInfoStore";
  6. import { neReg } from "@/utils";
  7. import { Form, Input, Toast } from "antd-mobile";
  8. import { FormInstance } from "antd-mobile/es/components/form";
  9. import { useTranslations } from "next-intl";
  10. import { FC, Fragment, useRef, useState } from "react";
  11. import ButtonOwn from "@/components/ButtonOwn";
  12. import "@/styles/deposit.scss";
  13. import { Autoplay, Pagination } from "swiper/modules";
  14. import { Swiper, SwiperSlide } from "swiper/react";
  15. interface Props {
  16. deposits: DepositsTypes[];
  17. }
  18. const DepositData: FC<Props> = (props) => {
  19. const { deposits } = props;
  20. const t = useTranslations();
  21. const userInfo = useUserInfoStore((state) => state.userInfo);
  22. // 选中类型
  23. const [activeType, setActiveType] = useState<DepositsTypes>(deposits[0]);
  24. // 是否自定义充值
  25. const [isCustomInput, setIsCustomInput] = useState(false);
  26. const formInstanceRef = useRef<FormInstance>(null);
  27. let [amount, setAmount] = useState<number | undefined>(undefined);
  28. const titleChangeHandler = (item: DepositsTypes, index: number) => {
  29. setAmount(undefined);
  30. setActiveType(item);
  31. formInstanceRef.current?.resetFields();
  32. };
  33. const isStrictMode = true;
  34. const onFinish = (values: any) => {
  35. const params = { ...values, channel_id: activeType.id, amount: +values.amount };
  36. getUserRechargeApi(params)
  37. .then((res) => {
  38. formInstanceRef.current?.resetFields();
  39. Toast.show({ icon: "success", content: t("code.200"), maskClickable: false });
  40. setAmount(undefined);
  41. if (res.data.pay_url) {
  42. window.open(res.data.pay_url);
  43. }
  44. })
  45. .catch((error) => {
  46. Toast.show({ content: t(`code${error.data.code}`), maskClickable: false });
  47. });
  48. };
  49. const onValuesChange = (changeValues: any) => {
  50. if (changeValues.amount) {
  51. setAmount(changeValues.amount);
  52. }
  53. };
  54. const amountChange = (value: number) => {
  55. formInstanceRef.current?.setFieldValue("amount", value);
  56. setAmount(value);
  57. };
  58. const amountValidator = (rules: any, value: any) => {
  59. if (!value) return Promise.reject(new Error(t("form.amount")));
  60. if (+value < activeType.min_amount)
  61. return Promise.reject(
  62. new Error(t("form.amountMinReg", { amount: activeType.min_amount }))
  63. );
  64. if (+value > activeType.max_amount)
  65. return Promise.reject(
  66. new Error(t("form.amountMaxReg", { amount: activeType.max_amount }))
  67. );
  68. return Promise.resolve();
  69. };
  70. const banners = [
  71. {
  72. id: 61,
  73. sort: 0,
  74. show_platform: 1,
  75. action_type: 1,
  76. action_params: "",
  77. content: "http://192.168.0.237:9000/bcwin/86fa3351-2aef-4ede-ba70-cae365f03812.jpg",
  78. },
  79. {
  80. id: 62,
  81. sort: 0,
  82. show_platform: 1,
  83. action_type: 1,
  84. action_params: "",
  85. content: "http://192.168.0.237:9000/bcwin/9809de49-966e-4dea-81c9-baa71347dc6c.jpg",
  86. },
  87. ];
  88. return (
  89. <>
  90. <div style={{ height: "1.86rem" }} className={"home-banner"}>
  91. <Swiper
  92. autoplay={{ delay: 2500 }}
  93. pagination={{ clickable: true }}
  94. spaceBetween={10}
  95. scrollbar={{ draggable: true }}
  96. slidesPerView={1}
  97. loop
  98. modules={[Pagination, Autoplay]}
  99. >
  100. {banners.map((banner, index) => (
  101. <SwiperSlide key={index}>
  102. <Box
  103. none
  104. action={banner.action_type as 1}
  105. actionData={banner.action_params}
  106. >
  107. <img
  108. src={banner.content}
  109. style={{ height: "1.86rem", width: "100%" }}
  110. alt={"banner"}
  111. />
  112. </Box>
  113. </SwiperSlide>
  114. ))}
  115. </Swiper>
  116. </div>
  117. <div className="deposit-box">
  118. <p>title</p>
  119. <p className={"text-[0.12rem] text-[#e8e8e8]"}>
  120. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab accusamus amet
  121. animi beatae blanditiis cumque dicta dolor eius est ex, facilis illo libero
  122. magnam placeat quibusdam similique ullam, vel veniam?
  123. </p>
  124. <div className={"flex flex-wrap"}>
  125. {deposits.map((item, index) => {
  126. return (
  127. <Fragment key={item.id}>
  128. <p
  129. className="btn-box truncate"
  130. style={{
  131. borderColor: activeType.id === item.id ? "#ff9323" : "#333",
  132. }}
  133. onClick={() => titleChangeHandler(item, index)}
  134. >
  135. {item.name}
  136. </p>
  137. </Fragment>
  138. );
  139. })}
  140. </div>
  141. <Box className={"custom-form"} style={{ padding: 0 }}>
  142. <Form
  143. style={{
  144. "--border-bottom": "none",
  145. "--border-top": "none",
  146. "--border-inner": "none",
  147. }}
  148. ref={formInstanceRef}
  149. initialValues={userInfo}
  150. onFinish={onFinish}
  151. onValuesChange={onValuesChange}
  152. >
  153. {isStrictMode ? (
  154. <>
  155. <Form.Item
  156. name="user_name"
  157. label=""
  158. rules={[{ required: true, message: t("form.usernameReg") }]}
  159. >
  160. <Input placeholder={t("form.username")} />
  161. </Form.Item>
  162. <Form.Item
  163. name="passport"
  164. label=""
  165. rules={[
  166. {
  167. required: true,
  168. message: t("form.cardReg"),
  169. pattern: neReg,
  170. },
  171. ]}
  172. >
  173. <Input
  174. placeholder={t("form.card")}
  175. maxLength={11}
  176. type={"text"}
  177. />
  178. </Form.Item>
  179. </>
  180. ) : null}
  181. {isCustomInput && (
  182. <Form.Item
  183. name="amount"
  184. label=""
  185. rules={[
  186. { required: true, type: "number", validator: amountValidator },
  187. ]}
  188. >
  189. <Input
  190. placeholder={`${t("DepositPage.Montante")}(BRL): Mín. ${activeType.min_amount}`}
  191. type={"number"}
  192. maxLength={activeType.max_amount}
  193. />
  194. </Form.Item>
  195. )}
  196. <div className={"flex flex-col"}>
  197. <div className={"flex-1"}>
  198. <ul className="ul-box">
  199. {activeType.products.map((item, index) => (
  200. <li
  201. className={amount == item.amount ? "active" : ""}
  202. key={index}
  203. onClick={() => amountChange(item.amount)}
  204. >
  205. {!!item.badge && <span className="hot"></span>}
  206. <div className="amountContent">
  207. {/* <span className="iconfont icon-unit-brl"></span> */}
  208. <span className="iconfont">R$</span>
  209. <span> {item.amount}</span>
  210. </div>
  211. <span className="amountTips">
  212. {t("DepositPage.Oferecer")} 100%
  213. </span>
  214. </li>
  215. ))}
  216. </ul>
  217. </div>
  218. </div>
  219. </Form>
  220. </Box>
  221. <ButtonOwn
  222. style={{ marginTop: "0.1389rem" }}
  223. active
  224. callbackFun={() => setIsCustomInput(true)}
  225. >
  226. {t("DepositPage.customButtonText")}
  227. </ButtonOwn>
  228. </div>
  229. </>
  230. );
  231. };
  232. export default DepositData;